# -*- coding: utf-8 -*-
from Exceptions.LibraryException import LibraryException
from MediaCollection.Database import Database
from MediaCollection.Video.Film import Film

"""
Die Episoden-Klasse repräsentiert eine Episode einer Serie mit allen in der 
Datenbank gespeicherten Attributen. Über ein Objekt dieser Klasse können neue 
Einträge in die Datenbank eingefügt werden, im Gegenzug aber auch über die Id 
des Eintrags in der Datenbank die entsprechenden Informationen in das Objekt 
eingelesen werden.
Anmerkung: Jede Episode ist auch ein Film! Hierbei ist jedoch das Attribut 
'movie' auf 'False' gesetzt und weiterhin sind mehr Daten (Series, Season und
Episode) gespeichert. Die Angabe 'Episode' bezieht sich auf die Episodennr. in
der jeweiligen Staffel.

@author: Philipp Dermitzel
@date: 2011-04-08
@version: 1.0.1
@attention: Da ein Großteil der Videodateien nicht über Metadaten verfügt,
    muss zumindest der Name des Filmes über den Dateinamen bzw. den Pfad 
    ableitbar sein. Ohne diese Voraussetzung können die Filmdaten nicht korrekt
    eingelesen werden. Es wird eine der folgende Strukturierungen empfohlen:
        Filme/<Filmname>/Datei.<Dateiendung>
        Filme/<Filmname>.<Dateiendung>
    Bei Serien sollte eine der folgenden Strukturierungen eingehalten werden:
        Serien/<Serienname>/<Staffelnr>/<Episodennummer>.<Dateiendung>
    Ein (gutes) Beispiel wäre der folgende Baum:
        | Filme
        |--| Taxi_Driver
        |--|--| taxidriver.avi
        |--| Star_Wars_IV
        |--|--| sw4.avi
        | Serien
        |--| Breaking_Bad
        |--|--| Season_1
        |--|--|--| 01.avi
        |--|--|--| 02.avi       
"""
class Episode(Film):
    
    """
    ----------------------------------------------------------------------------
    Konstruktor
    ----------------------------------------------------------------------------
    """
    def __init__(self, id = None):
        Film.__init__(self)
        super(Episode, self).getData()['series'] = None
        super(Episode, self).getData()['season'] = None
        super(Episode, self).getData()['episode'] = None
        
        if id is not None:
            super(Episode, self).getData()['id'] = id
            self.getDataFromDb()
        
    """
    ----------------------------------------------------------------------------
    Getter und Setter
    ----------------------------------------------------------------------------
    """
    
    """
    Setzt die Attribute der Episode um diesen später erfolgreich in die 
    Datenbank einfügen zu können. Dafür sollte das übergebene Dictionary
    C(dataDict) alle eben dort beschriebenen Informationen enthalten.    
    @param dataDict: Alle benötigten Informationen zum Film (siehe C(Film) sowie
        die zusätzlichen Daten für die Serie.
        Die Episode bezeichnet die Nummer in der aktuellen Staffel (Season)
    @type dataDict: Dictionary
    @return: Das 'self'-Objekt (für Chaining)
    @rtype: Episode
    """
    def setData(self, dataDict):
        super(Episode, self).setData(dataDict)
        if 'series' in dataDict:
            super(Episode, self).getData()['series'] = dataDict['series']
        if 'season' in dataDict:
            super(Episode, self).getData()['season'] = dataDict['season']
        if 'episode' in dataDict:
            super(Episode, self).getData()['episode'] = dataDict['episode']
        super(Episode, self).getData()['movie'] = False
        return self
    
    """
    Setzt ein einzelnen Attribut der Episode. Die momentan genutzten Felder 
    sind alle Daten, die auch für die Klasse C(Film) genutzt werden sowie die
    folgenden: id, series, season, episode.
    @param key: Der Schlüssel.
    @type key: String
    @param value: Der zu setzende Wert.
    @type value: int oder String
    @return: Das 'self'-Objekt (für Chaining)
    @rtype: Episode
    """
    def setValue(self, key, value):
        if key == "series":
            super(Episode, self).getData()['series'] = value
        elif key == "season":
            super(Episode, self).getData()['season'] = value
        elif key == "episode":
            super(Episode, self).getData()['episode'] = value
        else: 
            raise LibraryException("\"%s\" ist kein valider Parameter" %key)
        return self
    
    """
    Getter.
    @return: Die ID der Serie in der Datenbank.
    @rtype: int
    """
    def getSeries(self):
        return super(Episode, self).getData()['series']
    
    """
    Getter.
    @return: Die Staffel-Nummer der Episode in der Datenbank.
    @rtype: int
    """
    def getSeason(self):
        return super(Episode, self).getData()['season']
    
    """
    Getter.
    @return: Die Episoden-Nummer dieser Staffel der Episode in der Datenbank.
    @rtype: int
    """
    def getEpisode(self):
        return super(Episode, self).getData()['episode']
    
    """
    ----------------------------------------------------------------------------
    Methoden der Klasse
    ----------------------------------------------------------------------------
    """    
    
    """
    Liest die Film- und die Episoden-Daten aus der Datenbank.
    @return: Das 'self'-Objekt (für Chaining)
    @rtype: Episode
    """
    def getDataFromDb(self):
        super(Episode, self).getDataFromDb()
        db = Database()
        if super(Episode, self).getData()['id'] is None:
            LibraryException('Keine ID übergeben')
        
        try: 
            db.select('*', 'Episode', {
                'id' : super(Episode, self).getData()['id']
            })
            curFilm = db.dbCursor.fetchone()
            super(Episode, self).getData()['series'] = curFilm[1]
            super(Episode, self).getData()['season'] = curFilm[2]
            super(Episode, self).getData()['episode'] = curFilm[3] 
        except: raise LibraryException('Episode nicht vorhanden')        
        return self
    
    """
    Speichert die Film- und Episoden-Daten in der Datenbank.
    @return: Das 'self'-Objekt (für Chaining)
    @rtype: Episode
    """   
    def insertIntoDb(self):
        super(Episode, self).insertIntoDb(getData = False)
        if (super(Episode, self).getData()['season'] is not None
        and super(Episode, self).getData()['id'] is not None):
            db = Database()
            db.savepoint("sp")
            try: 
                db.insert('Episode', {
                    'id'      : super(Episode, self).getData()['id'],
                    'series'  : super(Episode, self).getData()['series'],
                    'season'  : super(Episode, self).getData()['season'],
                    'episode' : super(Episode, self).getData()['episode']
                })
                self.getDataFromDb()
            except:
                db.rollback("sp")
                raise LibraryException('Konnte Daten nicht einfügen')
        else: raise LibraryException('Nicht alle Daten vorhanden')
        return self
    
    """
    Löscht eine Episode aus der Datenbank.
    @return: Das 'self'-Objekt (für Chaining)
    @rtype: Episode
    """    
    def deleteFromDb(self):
        if super(Episode, self).getData()['id'] is None:
            self.getDataFromDb()
        db = Database()        
        try: 
            db.delete('Film', {'id':super(Episode, self).getData()['id']})
            db.delete('Episode', {'id':super(Episode, self).getData()['id']})
        except: raise LibraryException('Episode nicht vorhanden')
        return self